package cn1socket;

import com.codename1.system.NativeLookup;

import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * Created by Franklin on 5/1/14.
 */
public class Socket {

	public static class NoNativeSocketException extends IOException {
		public NoNativeSocketException(String s) {
			super(s);
		}
	}

	private NativeSocket peer;

	public Socket(String host,int port) throws IOException {
		peer = (NativeSocket) NativeLookup.create(NativeSocket.class);
		if (peer == null) {
			throw new NoNativeSocketException("Native socket not found");
		}
		peer.connect(host,port);
		check();
	}

	private void check() throws IOException {
		String e = peer.getException();
		if( e==null )
			return;
		String msg = peer.getExceptionMessage();
		if( e.equals("IOException") )
			throw new IOException(msg);
		if( e.equals("EOFException") )
			throw new EOFException(msg);
		throw new RuntimeException(e);
	}

	public void close() throws IOException {
		peer.close();
		check();
	}

	public InputStream getInputStream() {
		return new SocketInputStream();
	}

	public OutputStream getOutputStream() {
		return new SocketOutputStream();
	}

	private class SocketInputStream extends InputStream {

		@Override public int available() throws IOException {
			int rtn = peer.available();
			check();
			return rtn;
		}

		@Override public int read() throws IOException {
			int rtn = peer.read();
			check();
			return rtn;
		}

		@Override public int read(byte[] b) throws IOException {
			return read(b,0,b.length);
		}

		@Override public int read(byte[] b, int off, int len) throws IOException {
			byte[] rtn = peer.read(len);
			check();
			if( rtn == null )
				return -1;
			System.arraycopy(rtn, 0, b, off, rtn.length);
			return rtn.length;
		}
	}

	private class SocketOutputStream extends OutputStream {

		@Override public void flush() throws IOException {
			peer.flush();
			check();
		}

		@Override public void write(int b) throws IOException {
			peer.write(b);
			check();
		}

		@Override public void write(byte[] b) throws IOException {
			peer.writeBuffer(b);
			check();
		}

		@Override public void write(byte[] b, int off, int len) throws IOException {
			peer.writeBuffer(b,off,len);
			check();
		}
	}
}
